// /////////////////////////////////////////////////////////////////////////////
//
// Name:            TextBillboardComponent.cpp
// Author:          Michael Bartsch (ZCCdark203)
//
// Desc :           Component wrapper of Irrlicht's IBillboardTextSceneNode.
//
// License:         Copyright (C) 2009 Michael Bartsch and Contributors
//
//                  This program is free software: you can redistribute it
//                  and/or modify it under the terms of the zlib/libpng License.
//                  See main.cpp for conditions of distribution and use.
//
// /////////////////////////////////////////////////////////////////////////////

// Include files
#include "TextBillboardComponent.h"
#include "../../core/GameManager.h"


// TextBillboardComponent class
// TextBillboardComponent constructor (default).
TextBillboardComponent::TextBillboardComponent(Entity *parent)
: BillboardComponent(parent, true)
{
    if(pParent != NULL)
    {
       init(GameManager::Instance()->getGUIEnvironment()->getBuiltInFont(), 0,
            dimension2df(10.0f, 10.0f), SColor(255, 255, 255, 255), SColor(255, 255, 255, 255));
    }
}

// TextBillboardComponent constructor.
TextBillboardComponent::TextBillboardComponent(Entity *parent, const std::string &fontFileName,
                                               const wchar_t *text, const dimension2df &size,
                                               const SColor &colorTop, const SColor &colorBottom)
: BillboardComponent(parent, true)
{
    if(pParent != NULL)
    {
       init(GameManager::Instance()->getGUIEnvironment()->getFont(fontFileName.c_str()),
            text, size, colorTop, colorBottom);
    }
}

// TextBillboardComponent constructor.
TextBillboardComponent::TextBillboardComponent(Entity *parent, const std::string &fontFileName,
                                               const std::string &text, const dimension2df &size,
                                               const SColor &colorTop, const SColor &colorBottom)
: BillboardComponent(parent, true)
{
    if(pParent != NULL)
    {
       core::stringw wBuffer = core::stringw(text.c_str());
       init(GameManager::Instance()->getGUIEnvironment()->getFont(fontFileName.c_str()),
            wBuffer.c_str(), size, colorTop, colorBottom);
    }
}

// TextBillboardComponent deconstructor.
TextBillboardComponent::~TextBillboardComponent()
{
    if(pParent != NULL)
    {
       mBillboardTextSN->remove();
       mBillboardSN = NULL;
       mSceneNode = NULL;
    }
}

// Common initialisation method.
void TextBillboardComponent::init(IGUIFont *font, const wchar_t *text, const dimension2df &size,
                                  const SColor &colorTop, const SColor &colorBottom)
{
    // Get pointers to needed sub-systems of the Game Manager.
    ISceneManager *pSceneMgr = GameManager::Instance()->getSceneManager();

    // Create internal scene node.
    mBillboardTextSN = pSceneMgr->addBillboardTextSceneNode(font, text, 0, size,
                                                            pParent->getAbsolutePosition(),
                                                            pParent->getID(),
                                                            colorTop, colorBottom);
    mBillboardSN = mBillboardTextSN;
    mSceneNode = mBillboardTextSN;

    // Set-up internal mechanism for collision detection.
    mTriSelector = pSceneMgr->createTriangleSelectorFromBoundingBox(mBillboardTextSN);
    mMetaSelector = pSceneMgr->createMetaTriangleSelector();

    // Misc
    mText = text;
}

// Returns a direct pointer to the IBillboardTextSceneNode.
IBillboardTextSceneNode* TextBillboardComponent::getBillboardTextSceneNode()
 {
     return mBillboardTextSN;
 }

// Sets the text string.
void TextBillboardComponent::setText(const std::string &text)
{
    core::stringw wBuffer = core::stringw(text.c_str());
    mBillboardTextSN->setText(wBuffer.c_str());
}

// Sets the text string.
void TextBillboardComponent::setText(const wchar_t *text)
{
    mBillboardTextSN->setText(text);
    mText = text;
}

// Sets the color of the text.
void TextBillboardComponent::setTextColor(const SColor &color)
{
    mBillboardTextSN->setTextColor(color);
    mTextColor = color;
}

// Serializes this object.
bool TextBillboardComponent::onSerialization(SerializedAttributes *attributes)
{
    // Create a root.
    SerializedAttributes *root = new SerializedAttributes();

    // Serialize SceneComponent elements.
    SceneComponent::onSerialization(root);

    // Serialize attributes.
    root->pushStringW("text" , mText);
    root->pushColor("textColor", mTextColor);

    // Add root to the given collection of attributes.
    attributes->pushObject("TextBillboardComponent", root);
    root->drop();

    // Return
    return true;
}

// Deserializes this object.
bool TextBillboardComponent::onDeserialization(SerializedAttributes *attributes)
{
    // Retrieve root attribute from the collection.
    SerializedAttribute *rootAttribute = attributes->pullAttribute();

    if(rootAttribute == NULL || rootAttribute->getName() != "TextBillboardComponent")
      return false;

    SerializedAttributes *root = reinterpret_cast<SerializedAttributes*>(rootAttribute->getObject());
    root->grab();

    rootAttribute->drop(); // We no longer need this attribute.

    // Process all attributes in the root collection.
    for(SerializedAttribute *attribute = root->pullAttribute(); attribute != NULL; attribute = root->pullAttribute())
    {
       // Deserialize attributes
       if(attribute->getName() == "BillboardComponent")
       {
           // Rewrap attribute so that it can be deserialized properly.
           SerializedAttributes *wrappedAttribute = new SerializedAttributes();
           wrappedAttribute->pushAttribute(attribute);

           // Deserialize the component.
           BillboardComponent::onDeserialization(wrappedAttribute);

           // Clean up.
           wrappedAttribute->drop();
       }

       else if(attribute->getName() == "text")        setText((attribute->getStringW()).c_str());
       else if(attribute->getName() == "textColor")   setTextColor(attribute->getColor());

       // We no longer need a reference to the attribute.
       attribute->drop();
    }

    // We no longer need a reference to the root.
    root->drop();

    // We're done.
    return true;
}

// End of File
